#include "Function.hpp"
#include "EquationSolver.hpp"
#include <iostream>
#include <iomanip>
#include <cmath>
const double Pi = acos(-1.0);  // Define constant for Pi

// Constants
const double L = 10.0;  // Length of the trough in feet
const double r = 1.0;   // Radius of the semi-circle in feet
const double V = 12.4;  // Volume of the water in cubic feet

// Class F10: Represents the volume function f(h) for the trough
class F10 : public Function {
public:
    double operator() (double h) const {
        return L * (0.5 * Pi * r * r - r * r * asin(h / r) - h * sqrt(r * r - h * h)) - V;
    }
};

// Function to solve the volume equation using Bisection Method
void solve_bisection_method(double a, double b) {
    std::cout << "Solving volume equation using Bisection method on [" << a << ", " << b << "]" << std::endl;
    Bisection_Method solver(F10(), a, b);  // Initialize Bisection Method solver
    double h = solver.solve();  // Solve for the water depth h
    std::cout << "An approximation of h is: " << h << " ft" << std::endl;
    std::cout << std::fixed << std::setprecision(2) << "The depth of water is approximately " << r - h << " ft" << std::endl << std::endl;
}

// Function to solve the volume equation using Newton Method
void solve_newton_method(double x0) {
    std::cout << "Solving volume equation using Newton method from "<< x0 << std::endl;
    Newton_Method solver(F10(), x0);  // Initialize Newton Method solver
    double h = solver.solve();  // Solve for the water depth h
    std::cout << "An approximation of h is: " << h << " ft" << std::endl;
    std::cout << std::fixed << std::setprecision(2) << "The depth of water is approximately " << r - h << " ft" << std::endl << std::endl;
}

// Function to solve the volume equation using Secant Method
void solve_secant_method(double x0, double x1) {
    std::cout << "Solving volume equation using Secant method from " << x0 << " and " << x1 << std::endl;
    Secant_Method solver(F10(), x0, x1);  // Initialize Secant Method solver
    double h = solver.solve();  // Solve for the water depth h
    std::cout << "An approximation of h is: " << h << " ft" << std::endl;
    std::cout << std::fixed << std::setprecision(2) << "The depth of water is approximately " << r - h << " ft" << std::endl << std::endl;
}
int main() {
    solve_bisection_method(0.0, 1.0);
    solve_newton_method(0.5);
    solve_secant_method(0.0, 0.5);
    return 0;
}
